/**
 * <copyright>
 * </copyright>
 *
 * 
 */
package de.claaswilke.presents.resource.presents.mopp;

public class PresentsReferenceResolverSwitch implements de.claaswilke.presents.resource.presents.IPresentsReferenceResolverSwitch {
	
	/**
	 * This map stores a copy of the options the were set for loading the resource.
	 */
	private java.util.Map<Object, Object> options;
	
	protected de.claaswilke.presents.resource.presents.analysis.ConflictConflictorReferenceResolver conflictConflictorReferenceResolver = new de.claaswilke.presents.resource.presents.analysis.ConflictConflictorReferenceResolver();
	protected de.claaswilke.presents.resource.presents.analysis.ConflictConflicteesReferenceResolver conflictConflicteesReferenceResolver = new de.claaswilke.presents.resource.presents.analysis.ConflictConflicteesReferenceResolver();
	protected de.claaswilke.presents.resource.presents.analysis.PastPresentFromReferenceResolver pastPresentFromReferenceResolver = new de.claaswilke.presents.resource.presents.analysis.PastPresentFromReferenceResolver();
	protected de.claaswilke.presents.resource.presents.analysis.PastPresentRulePersonReferenceResolver pastPresentRulePersonReferenceResolver = new de.claaswilke.presents.resource.presents.analysis.PastPresentRulePersonReferenceResolver();
	
	public de.claaswilke.presents.resource.presents.IPresentsReferenceResolver<de.claaswilke.presents.Conflict, de.claaswilke.presents.Person> getConflictConflictorReferenceResolver() {
		return getResolverChain(de.claaswilke.presents.PresentsPackage.eINSTANCE.getConflict_Conflictor(), conflictConflictorReferenceResolver);
	}
	
	public de.claaswilke.presents.resource.presents.IPresentsReferenceResolver<de.claaswilke.presents.Conflict, de.claaswilke.presents.Person> getConflictConflicteesReferenceResolver() {
		return getResolverChain(de.claaswilke.presents.PresentsPackage.eINSTANCE.getConflict_Conflictees(), conflictConflicteesReferenceResolver);
	}
	
	public de.claaswilke.presents.resource.presents.IPresentsReferenceResolver<de.claaswilke.presents.PastPresent, de.claaswilke.presents.Person> getPastPresentFromReferenceResolver() {
		return getResolverChain(de.claaswilke.presents.PresentsPackage.eINSTANCE.getPastPresent_From(), pastPresentFromReferenceResolver);
	}
	
	public de.claaswilke.presents.resource.presents.IPresentsReferenceResolver<de.claaswilke.presents.PastPresentRule, de.claaswilke.presents.Person> getPastPresentRulePersonReferenceResolver() {
		return getResolverChain(de.claaswilke.presents.PresentsPackage.eINSTANCE.getPastPresentRule_Person(), pastPresentRulePersonReferenceResolver);
	}
	
	public void setOptions(java.util.Map<?, ?> options) {
		if (options != null) {
			this.options = new java.util.LinkedHashMap<Object, Object>();
			this.options.putAll(options);
		}
		conflictConflictorReferenceResolver.setOptions(options);
		conflictConflicteesReferenceResolver.setOptions(options);
		pastPresentFromReferenceResolver.setOptions(options);
		pastPresentRulePersonReferenceResolver.setOptions(options);
	}
	
	public void resolveFuzzy(String identifier, org.eclipse.emf.ecore.EObject container, org.eclipse.emf.ecore.EReference reference, int position, de.claaswilke.presents.resource.presents.IPresentsReferenceResolveResult<org.eclipse.emf.ecore.EObject> result) {
		if (container == null) {
			return;
		}
		if (de.claaswilke.presents.PresentsPackage.eINSTANCE.getConflict().isInstance(container)) {
			PresentsFuzzyResolveResult<de.claaswilke.presents.Person> frr = new PresentsFuzzyResolveResult<de.claaswilke.presents.Person>(result);
			String referenceName = reference.getName();
			org.eclipse.emf.ecore.EStructuralFeature feature = container.eClass().getEStructuralFeature(referenceName);
			if (feature != null && feature instanceof org.eclipse.emf.ecore.EReference && referenceName != null && referenceName.equals("conflictor")) {
				conflictConflictorReferenceResolver.resolve(identifier, (de.claaswilke.presents.Conflict) container, (org.eclipse.emf.ecore.EReference) feature, position, true, frr);
			}
		}
		if (de.claaswilke.presents.PresentsPackage.eINSTANCE.getConflict().isInstance(container)) {
			PresentsFuzzyResolveResult<de.claaswilke.presents.Person> frr = new PresentsFuzzyResolveResult<de.claaswilke.presents.Person>(result);
			String referenceName = reference.getName();
			org.eclipse.emf.ecore.EStructuralFeature feature = container.eClass().getEStructuralFeature(referenceName);
			if (feature != null && feature instanceof org.eclipse.emf.ecore.EReference && referenceName != null && referenceName.equals("conflictees")) {
				conflictConflicteesReferenceResolver.resolve(identifier, (de.claaswilke.presents.Conflict) container, (org.eclipse.emf.ecore.EReference) feature, position, true, frr);
			}
		}
		if (de.claaswilke.presents.PresentsPackage.eINSTANCE.getPastPresent().isInstance(container)) {
			PresentsFuzzyResolveResult<de.claaswilke.presents.Person> frr = new PresentsFuzzyResolveResult<de.claaswilke.presents.Person>(result);
			String referenceName = reference.getName();
			org.eclipse.emf.ecore.EStructuralFeature feature = container.eClass().getEStructuralFeature(referenceName);
			if (feature != null && feature instanceof org.eclipse.emf.ecore.EReference && referenceName != null && referenceName.equals("from")) {
				pastPresentFromReferenceResolver.resolve(identifier, (de.claaswilke.presents.PastPresent) container, (org.eclipse.emf.ecore.EReference) feature, position, true, frr);
			}
		}
		if (de.claaswilke.presents.PresentsPackage.eINSTANCE.getPastPresentRule().isInstance(container)) {
			PresentsFuzzyResolveResult<de.claaswilke.presents.Person> frr = new PresentsFuzzyResolveResult<de.claaswilke.presents.Person>(result);
			String referenceName = reference.getName();
			org.eclipse.emf.ecore.EStructuralFeature feature = container.eClass().getEStructuralFeature(referenceName);
			if (feature != null && feature instanceof org.eclipse.emf.ecore.EReference && referenceName != null && referenceName.equals("person")) {
				pastPresentRulePersonReferenceResolver.resolve(identifier, (de.claaswilke.presents.PastPresentRule) container, (org.eclipse.emf.ecore.EReference) feature, position, true, frr);
			}
		}
	}
	
	public de.claaswilke.presents.resource.presents.IPresentsReferenceResolver<? extends org.eclipse.emf.ecore.EObject, ? extends org.eclipse.emf.ecore.EObject> getResolver(org.eclipse.emf.ecore.EStructuralFeature reference) {
		if (reference == de.claaswilke.presents.PresentsPackage.eINSTANCE.getConflict_Conflictor()) {
			return getResolverChain(reference, conflictConflictorReferenceResolver);
		}
		if (reference == de.claaswilke.presents.PresentsPackage.eINSTANCE.getConflict_Conflictees()) {
			return getResolverChain(reference, conflictConflicteesReferenceResolver);
		}
		if (reference == de.claaswilke.presents.PresentsPackage.eINSTANCE.getPastPresent_From()) {
			return getResolverChain(reference, pastPresentFromReferenceResolver);
		}
		if (reference == de.claaswilke.presents.PresentsPackage.eINSTANCE.getPastPresentRule_Person()) {
			return getResolverChain(reference, pastPresentRulePersonReferenceResolver);
		}
		return null;
	}
	
	@SuppressWarnings({"rawtypes", "unchecked"})	
	public <ContainerType extends org.eclipse.emf.ecore.EObject, ReferenceType extends org.eclipse.emf.ecore.EObject> de.claaswilke.presents.resource.presents.IPresentsReferenceResolver<ContainerType, ReferenceType> getResolverChain(org.eclipse.emf.ecore.EStructuralFeature reference, de.claaswilke.presents.resource.presents.IPresentsReferenceResolver<ContainerType, ReferenceType> originalResolver) {
		if (options == null) {
			return originalResolver;
		}
		Object value = options.get(de.claaswilke.presents.resource.presents.IPresentsOptions.ADDITIONAL_REFERENCE_RESOLVERS);
		if (value == null) {
			return originalResolver;
		}
		if (!(value instanceof java.util.Map)) {
			// send this to the error log
			new de.claaswilke.presents.resource.presents.util.PresentsRuntimeUtil().logWarning("Found value with invalid type for option " + de.claaswilke.presents.resource.presents.IPresentsOptions.ADDITIONAL_REFERENCE_RESOLVERS + " (expected " + java.util.Map.class.getName() + ", but was " + value.getClass().getName() + ")", null);
			return originalResolver;
		}
		java.util.Map<?,?> resolverMap = (java.util.Map<?,?>) value;
		Object resolverValue = resolverMap.get(reference);
		if (resolverValue == null) {
			return originalResolver;
		}
		if (resolverValue instanceof de.claaswilke.presents.resource.presents.IPresentsReferenceResolver) {
			de.claaswilke.presents.resource.presents.IPresentsReferenceResolver replacingResolver = (de.claaswilke.presents.resource.presents.IPresentsReferenceResolver) resolverValue;
			if (replacingResolver instanceof de.claaswilke.presents.resource.presents.IPresentsDelegatingReferenceResolver) {
				// pass original resolver to the replacing one
				((de.claaswilke.presents.resource.presents.IPresentsDelegatingReferenceResolver) replacingResolver).setDelegate(originalResolver);
			}
			return replacingResolver;
		} else if (resolverValue instanceof java.util.Collection) {
			java.util.Collection replacingResolvers = (java.util.Collection) resolverValue;
			de.claaswilke.presents.resource.presents.IPresentsReferenceResolver replacingResolver = originalResolver;
			for (Object next : replacingResolvers) {
				if (next instanceof de.claaswilke.presents.resource.presents.IPresentsReferenceCache) {
					de.claaswilke.presents.resource.presents.IPresentsReferenceResolver nextResolver = (de.claaswilke.presents.resource.presents.IPresentsReferenceResolver) next;
					if (nextResolver instanceof de.claaswilke.presents.resource.presents.IPresentsDelegatingReferenceResolver) {
						// pass original resolver to the replacing one
						((de.claaswilke.presents.resource.presents.IPresentsDelegatingReferenceResolver) nextResolver).setDelegate(replacingResolver);
					}
					replacingResolver = nextResolver;
				} else {
					// The collection contains a non-resolver. Send a warning to the error log.
					new de.claaswilke.presents.resource.presents.util.PresentsRuntimeUtil().logWarning("Found value with invalid type in value map for option " + de.claaswilke.presents.resource.presents.IPresentsOptions.ADDITIONAL_REFERENCE_RESOLVERS + " (expected " + de.claaswilke.presents.resource.presents.IPresentsDelegatingReferenceResolver.class.getName() + ", but was " + next.getClass().getName() + ")", null);
				}
			}
			return replacingResolver;
		} else {
			// The value for the option ADDITIONAL_REFERENCE_RESOLVERS has an unknown type.
			new de.claaswilke.presents.resource.presents.util.PresentsRuntimeUtil().logWarning("Found value with invalid type in value map for option " + de.claaswilke.presents.resource.presents.IPresentsOptions.ADDITIONAL_REFERENCE_RESOLVERS + " (expected " + de.claaswilke.presents.resource.presents.IPresentsDelegatingReferenceResolver.class.getName() + ", but was " + resolverValue.getClass().getName() + ")", null);
			return originalResolver;
		}
	}
	
}
